package org.amn.concurrent;

import java.io.File;
import java.util.concurrent.TimeUnit;

import org.amn.dto.IndexDTO;
import org.amn.file.FileManager;
import org.amn.file.FileStatus;
import org.amn.file.FileUtils;
import org.apache.log4j.Logger;
import org.springframework.util.Assert;

/**
 * <p>
 * 描述:通过扫描，产生索引进入队列，
 * 考虑使用h2,在收消息时直接建立索引
 * speed:300 message /sec
 * </p>
 *
 * @see
 * @author yangjun2
 *
 */
public class Scanner implements Runnable {
    private static Logger logger = Logger.getLogger(Scanner.class);

    private IindexQueue<IndexDTO> q;

    private FileManager fm;

    private String[] dirs;

    private static String penddingPath;

    private static String enqueuePath;

    private static String exceptionPath;

    //private Manager mm;
    public Scanner(String[] aDirs, FileManager fileManager, IindexQueue<IndexDTO> queue) {
        Assert.notNull(aDirs, "scan dirs must be  not null");
        Assert.notNull(fileManager, "file manager  must be  not null");
        Assert.notNull(queue, "queue must be  not null");
        this.dirs = aDirs;
        this.fm = fileManager;
        this.q = queue;

        if (penddingPath == null)
            penddingPath = fm.getPath(FileStatus.PENDDING);

        if (enqueuePath == null)
            enqueuePath = fm.getPath(FileStatus.ENQUEUE);

        if (exceptionPath == null) {
            exceptionPath = fm.getPath(FileStatus.EXCEPTION);
        }
    }

    private void scan() {
        try {

            for (String d : dirs) {
                File f = new File(d);
                File[] listFiles = f.listFiles();

                for (File tf : listFiles) {
                    if (tf.isFile()) {
                        //move
                        String fName = tf.getName();
                        String absolutePath = tf.getAbsolutePath();
                        String queuePath = enqueuePath;
                        String expDestPath = exceptionPath;
                        String newQueFileName = null;
                        String newExpFileName = null;
                        String folder = FileUtils.getFolder();

                        if (absolutePath.indexOf(penddingPath) > -1) {
                            //正常待处理

                            folder = absolutePath.substring(absolutePath.indexOf(penddingPath) + penddingPath.length()
                                    + 1, absolutePath.indexOf(fName) - 1);

                            //正常enqueue目录
                            newQueFileName = queuePath + File.separator + folder + File.separator + fName;

                            //异常exception目录
                            newExpFileName = expDestPath + File.separator + folder + File.separator + fName;

                            if ((!FileUtils.renameTo(tf, newQueFileName) && (!FileUtils.renameTo(tf, newExpFileName)))) {
                                logger.error("failure to rename file to exception path ,source path:" + absolutePath
                                        + ",destination path:" + newExpFileName);

                            } else {

                                IndexDTO idx = new IndexDTO();
                                idx.setId(fName);
                                idx.setPath(newQueFileName);
                                idx.setLastModified(System.currentTimeMillis());

                                boolean offer = q.offer(idx);

                                if (offer) {
                                    if (logger.isDebugEnabled()) {
                                        logger.debug("add queue:" + idx.getId() + ",path:" + idx.getPath());
                                    }

                                } else { // queue is full
                                    if (logger.isInfoEnabled()) {
                                        logger.info("queue is full,scanner finish!");
                                    }
                                    break;
                                }
                            }

                        } else if ((absolutePath.indexOf(enqueuePath) > -1)) {
                            if (isTimeout(tf, fm.getFileTimeout())) {

                                newQueFileName = queuePath + File.separator + folder + File.separator
                                        + FileUtils.formatFileName(fName);

                                newExpFileName = expDestPath + File.separator + folder + File.separator
                                        + FileUtils.formatFileName(fName);

                                if ((!FileUtils.renameTo(tf, newQueFileName) && (!FileUtils
                                        .renameTo(tf, newExpFileName)))) {
                                    logger.error("failure to rename file to exception path ,source path:"
                                            + absolutePath + ",destination path:" + newExpFileName);

                                }
                                //超时待处理

                                //为了加速处理，不做队列contains和remove动作。
                            }

                        }

                    }
                }

                //清理过期的空目录,包括pendding,enqueue目录
                if (isTimeout(f, fm.getEmptyPathTimeout())) {
                    if ((f.list().length == 0) && (!FileUtils.deleteFile(f))) {
                        logger.error("failure to delete file, path:" + f.getAbsolutePath());
                    }

                }

            }
        } catch (Throwable e) {
            logger.error("scan path exception", e);
        }

    }

    private boolean isTimeout(File f, long t) {

        long timeout = t;
        TimeUnit timeUnit = fm.getTimeUnit();
        long s = TimeUnit.MILLISECONDS.convert(timeout, timeUnit);

        if ((System.currentTimeMillis() - f.lastModified()) >= s) {
            return true;
        }
        return false;
    }

    @Override
    public void run() {
        System.out.println("scan is running,id:" + Thread.currentThread());
        try {
            scan();
        } catch (Throwable e) {
            logger.error("scanner run exception", e);
        }
    }

    public static void main(String[] args) throws Exception {

        Thread.sleep(30 * 1000);

        File f = new File("D:\\work\\j2eeproject\\amesb\\build.xml");
        System.out.println(f.getName());

    }
}
